package com.wgz.medicalmanagement.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.wgz.medicalmanagement.common.exception.BusinessException;
import com.wgz.medicalmanagement.domain.dto.PatientDTO;
import com.wgz.medicalmanagement.domain.dto.PatientQueryDTO;
import com.wgz.medicalmanagement.domain.entity.Patient;
import com.wgz.medicalmanagement.repository.PatientRepository;
import com.wgz.medicalmanagement.service.PatientService;

import jakarta.persistence.criteria.Predicate;

/**
 * 患者管理服务实现类
 */
@Service
public class PatientServiceImpl implements PatientService {

    @Autowired
    private PatientRepository patientRepository;

    @Override
    public Page<PatientDTO> getPatientList(PatientQueryDTO queryDTO) {
        // 构建查询条件
        Specification<Patient> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 根据姓名模糊查询
            if (StringUtils.hasText(queryDTO.getName())) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + queryDTO.getName() + "%"));
            }
            
            // 根据身份证号查询
            if (StringUtils.hasText(queryDTO.getIdCard())) {
                predicates.add(criteriaBuilder.like(root.get("idCard"), "%" + queryDTO.getIdCard() + "%"));
            }
            
            // 根据手机号查询
            if (StringUtils.hasText(queryDTO.getPhone())) {
                predicates.add(criteriaBuilder.like(root.get("phone"), "%" + queryDTO.getPhone() + "%"));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        // 创建分页对象
        Pageable pageable = PageRequest.of(queryDTO.getPage(), queryDTO.getSize());
        
        // 查询数据
        Page<Patient> patientPage = patientRepository.findAll(specification, pageable);
        
        // 转换为DTO
        List<PatientDTO> patientDTOList = patientPage.getContent().stream()
                .map(this::buildPatientDTO)
                .toList();
        
        return new PageImpl<>(patientDTOList, pageable, patientPage.getTotalElements());
    }

    @Override
    public PatientDTO getPatientDetail(Long id) {
        Optional<Patient> patientOptional = patientRepository.findById(id);
        if (patientOptional.isEmpty()) {
            throw new BusinessException("患者不存在");
        }
        return buildPatientDTO(patientOptional.get());
    }

    @Override
    @Transactional
    public PatientDTO addPatient(PatientDTO patientDTO) {
        // 检查身份证号是否存在
        if (StringUtils.hasText(patientDTO.getIdCard())) {
            Patient existingPatient = patientRepository.findByIdCard(patientDTO.getIdCard());
            if (existingPatient != null) {
                throw new BusinessException("该身份证号已存在");
            }
        }
        
        // 检查手机号是否存在
        if (StringUtils.hasText(patientDTO.getPhone())) {
            Patient existingPatient = patientRepository.findByPhone(patientDTO.getPhone());
            if (existingPatient != null) {
                throw new BusinessException("该手机号已存在");
            }
        }
        
        // 构建实体并保存
        Patient patient = buildPatientEntity(patientDTO);
        patient.setCreatedTime(LocalDateTime.now());
        patient.setUpdatedTime(LocalDateTime.now());
        patient.setDeleted(0); // 未删除
        
        Patient savedPatient = patientRepository.save(patient);
        return buildPatientDTO(savedPatient);
    }

    @Override
    @Transactional
    public PatientDTO updatePatient(Long id, PatientDTO patientDTO) {
        // 检查患者是否存在
        Optional<Patient> patientOptional = patientRepository.findById(id);
        if (patientOptional.isEmpty()) {
            throw new BusinessException("患者不存在");
        }
        
        Patient existingPatient = patientOptional.get();
        
        // 检查身份证号是否存在（排除当前患者）
        if (StringUtils.hasText(patientDTO.getIdCard()) && !patientDTO.getIdCard().equals(existingPatient.getIdCard())) {
            Patient duplicatePatient = patientRepository.findByIdCard(patientDTO.getIdCard());
            if (duplicatePatient != null) {
                throw new BusinessException("该身份证号已存在");
            }
        }
        
        // 检查手机号是否存在（排除当前患者）
        if (StringUtils.hasText(patientDTO.getPhone()) && !patientDTO.getPhone().equals(existingPatient.getPhone())) {
            Patient duplicatePatient = patientRepository.findByPhone(patientDTO.getPhone());
            if (duplicatePatient != null) {
                throw new BusinessException("该手机号已存在");
            }
        }
        
        // 更新患者信息
        BeanUtils.copyProperties(patientDTO, existingPatient, "id", "createdTime", "deleted");
        existingPatient.setUpdatedTime(LocalDateTime.now());
        
        Patient updatedPatient = patientRepository.save(existingPatient);
        return buildPatientDTO(updatedPatient);
    }

    @Override
    @Transactional
    public void deletePatient(Long id) {
        // 检查患者是否存在
        Optional<Patient> patientOptional = patientRepository.findById(id);
        if (patientOptional.isEmpty()) {
            throw new BusinessException("患者不存在");
        }
        
        // 逻辑删除
        Patient patient = patientOptional.get();
        patient.setDeleted(1); // 已删除
        patient.setUpdatedTime(LocalDateTime.now());
        patientRepository.save(patient);
    }

    @Override
    public PatientDTO buildPatientDTO(Patient patient) {
        if (patient == null) {
            return null;
        }
        
        PatientDTO patientDTO = new PatientDTO();
        BeanUtils.copyProperties(patient, patientDTO);
        return patientDTO;
    }

    @Override
    public Patient buildPatientEntity(PatientDTO patientDTO) {
        if (patientDTO == null) {
            return null;
        }
        
        Patient patient = new Patient();
        BeanUtils.copyProperties(patientDTO, patient);
        return patient;
    }
} 